/*
 * $Id: Sio.cc,v 1.6 2006-02-07 05:53:45 bacon Exp $
 */

#include <xpp/bas/Sio.h>

// TODO: complete this class....

namespace xpp
{
	namespace bas
	{

		Sio::~Sio ()
		{
			close ();
		}


		int Sio::open (const xp_char_t* path, const xp_char_t* mode)
		{
			xp_assert (this->sio == XP_NULL);
			this->sio = xp_sio_open (XP_NULL, path, mode);
			if (this->sio == XP_NULL) return -1;
			return 0;	
		}

		int Sio::opentmp (xp_char_t* tmpl, bool unlink_after_open)
		{
			xp_assert (this->sio == XP_NULL);
			xp_hnd_t hnd = xp_opentmp (tmpl);
			if (hnd == XP_HND_INVALID) return -1;

			this->sio = xp_sio_openhnd (XP_NULL, hnd);
			if (this->sio == XP_NULL) {
				xp_close (hnd);
				xp_unlink (tmpl);
				return -1;
			}

		#ifndef _WIN32
			if (unlink_after_open) xp_unlink(tmpl);
		#endif
			return 0;
		}

		int Sio::close ()
		{
			int n = 0;
			if (this->sio != XP_NULL) {
				if (this->sio != xp_sio_in &&
				    this->sio != xp_sio_out &&
				    this->sio != xp_sio_err) {
					n = xp_sio_close (this->sio);
				}

				this->sio = XP_NULL;
			}	
			return n;
		}

		xp_tri_t Sio::readLine (String* line)
		{
			xp_assert (this->sio != XP_NULL);

			line->remove ();

			xp_ssize_t n;
			xp_char_t c;

			for (;;) {
				n = xp_sio_getc (this->sio, &c);
				if (n == -1) return xp_dead;
				if (n == 0) {
					if (line->length() == 0) {
						/* no more data */
						return xp_zombie; 
					}

					break;
				}

				if (c == XP_CHAR('\n')) {
					xp_size_t len = line->length();
					if (len > 0 && line->charAt(len - 1) == XP_CHAR('\r')) {
						line->remove (len - 1, 1);
					}
					break;
				}	
				line->append (c);
			}

			return xp_alive;
		}

	}
}
